<template>
    <div ref="chartRef" class="pie3d-container"></div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import 'echarts-gl'; // 3D 图表依赖，必须引入

// 1. 组件 props：支持外部传递数据，提高复用性
const props = defineProps({
    /** 饼图数据：格式 [{name: string, value: number, itemStyle?: {color: string}}] */
    pieData: {
        type: Array,
    },
    /** 内直径比例（0~1）：控制饼图内环大小 */
    internalDiameterRatio: {
        type: Number,
    },
    /** 图表高度 */
    chartHeight: {
        type: String,
    }
});

// 2. 核心变量
const chartRef = ref(null); // 图表容器 DOM 引用
let chartInstance = null;  // ECharts 实例
let selectedIndex = '';    // 选中的扇形索引
let hoveredIndex = '';     //  hover 的扇形索引

// 3. 3D 饼图参数方程：生成扇形曲面
const getParametricEquation = (startRatio, endRatio, isSelected, isHovered, k, h) => {
    const midRatio = (startRatio + endRatio) / 2;
    const startRadian = startRatio * Math.PI * 2;
    const endRadian = endRatio * Math.PI * 2;
    const midRadian = midRatio * Math.PI * 2;

    // 单个扇形不显示选中效果
    if (startRatio === 0 && endRatio === 1) isSelected = false;

    // 内径/外径比例（默认 1/3）
    k = typeof k !== 'undefined' ? k : 1 / 3;

    // 选中时的位移
    const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
    const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;

    //  hover 时的放大比例
    const hoverRate = isHovered ? 1.05 : 1;

    return {
        u: { min: -Math.PI, max: Math.PI * 3, step: Math.PI / 32 },
        v: { min: 0, max: Math.PI * 2, step: Math.PI / 20 },
        x: (u, v) => {
            if (u < startRadian) return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
            if (u > endRadian) return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
            return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
        },
        y: (u, v) => {
            if (u < startRadian) return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
            if (u > endRadian) return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
            return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
        },
        z: (u, v) => {
            if (u < -Math.PI * 0.5) return Math.sin(u);
            if (u > Math.PI * 2.5) return Math.sin(u) * h * 0.1;
            return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
        }
    };
};

// 4. 生成 3D 饼图配置项
const getPie3D = () => {
    const { pieData, internalDiameterRatio } = props;
    const series = [];
    let sumValue = 0;
    let startValue = 0;
    let endValue = 0;
    let legendData = [];
    const k = (1 - internalDiameterRatio) / (1 + internalDiameterRatio);

    // 1. 生成每个扇形的 surface 系列
    pieData.forEach(item => {
        sumValue += item.value;
        const seriesItem = {
            name: item.name || `series${series.length}`,
            type: 'surface',
            parametric: true,
            wireframe: { show: false },
            pieData: item,
            pieStatus: { selected: false, hovered: false, k },
            itemStyle: {}
        };

        // 继承外部传递的 itemStyle(自定义颜色)
        // if (item.itemStyle) {
        //     seriesItem.itemStyle.color = item.itemStyle.color;
        //     seriesItem.itemStyle.opacity = item.itemStyle.opacity;
        // }

        series.push(seriesItem);
    });

    // 2. 为每个系列设置参数方程（实现扇形分割）
    series.forEach(item => {
        endValue = startValue + item.pieData.value;
        item.pieData.startRatio = startValue / sumValue;
        item.pieData.endRatio = endValue / sumValue;
        item.parametricEquation = getParametricEquation(
            item.pieData.startRatio,
            item.pieData.endRatio,
            false,
            false,
            k,
            item.pieData.value
        );
        startValue = endValue;
        legendData.push(item.name);
    });

    // 3. 添加透明圆环：用于支撑 hover 交互
    series.push({
        name: 'mouseoutSeries',
        type: 'surface',
        parametric: true,
        wireframe: { show: false },
        itemStyle: { opacity: 0 },
        parametricEquation: {
            u: { min: 0, max: Math.PI * 2, step: Math.PI / 20 },
            v: { min: 0, max: Math.PI, step: Math.PI / 20 },
            x: (u, v) => Math.sin(v) * Math.sin(u) + Math.sin(u),
            y: (u, v) => Math.sin(v) * Math.cos(u) + Math.cos(u),
            z: (u, v) => Math.cos(v) > 0 ? 0.1 : -0.1
        }
    });

    // 4. 完整配置项
    return {
        animation: true,
        legend: {
            data: legendData,
            textStyle: { color: '#fff' }, // 适配深色背景
            top: 20
        },
        tooltip: {
            formatter: params => {
                if (params.seriesName !== 'mouseoutSeries') {
                    return `${params.seriesName}<br/>
            <span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${params.color};"></span>
            ${series[params.seriesIndex].pieData.value}`;
                }
            },
            backgroundColor: 'rgba(0,0,0,0.7)',
            textStyle: { color: '#fff' }
        },
        xAxis3D: { min: -1, max: 1, axisLine: { show: false }, tickLine: { show: false } },
        yAxis3D: { min: -1, max: 1, axisLine: { show: false }, tickLine: { show: false } },
        zAxis3D: { min: -1, max: 1, axisLine: { show: false }, tickLine: { show: false } },
        grid3D: {
            show: false,
            boxHeight: 10,
            viewControl: {
                alpha: 40,
                rotateSensitivity: 0,
                zoomSensitivity: 0,
                panSensitivity: 0,
                autoRotate: false
            },
            postEffect: {
                enable: true,
                bloom: { enable: true, bloomIntensity: 0.1 },
                SSAO: { enable: true, quality: 'medium', radius: 2 }
            }
        },
        series
    };
};

// 5. 初始化图表
const initChart = () => {
    if (!chartRef.value) return;

    // 销毁旧实例（避免重复渲染）
    if (chartInstance) {
        chartInstance.dispose();
    }

    // 创建新实例
    chartInstance = echarts.init(chartRef.value);
    const option = getPie3D();
    chartInstance.setOption(option);

    // 6. 绑定鼠标交互事件
    bindChartEvents();

    // 窗口 resize 适配
    const handleResize = () => chartInstance?.resize();
    window.addEventListener('resize', handleResize);
    onUnmounted(() => window.removeEventListener('resize', handleResize));
};

// 7. 绑定图表交互事件（点击、hover、离开）
const bindChartEvents = () => {
    if (!chartInstance) return;
    const option = chartInstance.getOption();

    // 点击选中（单选）
    chartInstance.on('click', params => {
        if (params.seriesName === 'mouseoutSeries') return;

        const { seriesIndex } = params;
        const targetSeries = option.series[seriesIndex];
        const isSelected = !targetSeries.pieStatus.selected;
        const k = targetSeries.pieStatus.k;
        const { startRatio, endRatio, value } = targetSeries.pieData;

        // 取消之前选中的扇形
        if (selectedIndex !== '' && selectedIndex !== seriesIndex) {
            const prevSeries = option.series[selectedIndex];
            prevSeries.parametricEquation = getParametricEquation(
                prevSeries.pieData.startRatio,
                prevSeries.pieData.endRatio,
                false,
                false,
                k,
                prevSeries.pieData.value
            );
            prevSeries.pieStatus.selected = false;
        }

        // 更新当前选中状态
        targetSeries.parametricEquation = getParametricEquation(startRatio, endRatio, isSelected, false, k, value);
        targetSeries.pieStatus.selected = isSelected;
        selectedIndex = isSelected ? seriesIndex : '';

        chartInstance.setOption(option);
    });

    // 鼠标 hover 高亮
    chartInstance.on('mouseover', params => {
        if (params.seriesName === 'mouseoutSeries') return;
        if (hoveredIndex === params.seriesIndex) return;

        const { seriesIndex } = params;
        const targetSeries = option.series[seriesIndex];
        const k = targetSeries.pieStatus.k;
        const { startRatio, endRatio, value } = targetSeries.pieData;
        const isSelected = targetSeries.pieStatus.selected;

        // 取消之前 hover 的扇形
        if (hoveredIndex !== '') {
            const prevSeries = option.series[hoveredIndex];
            prevSeries.parametricEquation = getParametricEquation(
                prevSeries.pieData.startRatio,
                prevSeries.pieData.endRatio,
                prevSeries.pieStatus.selected,
                false,
                k,
                prevSeries.pieData.value
            );
            prevSeries.pieStatus.hovered = false;
        }

        // 更新当前 hover 状态
        targetSeries.parametricEquation = getParametricEquation(startRatio, endRatio, isSelected, true, k, value + 5);
        targetSeries.pieStatus.hovered = true;
        hoveredIndex = seriesIndex;

        chartInstance.setOption(option);
    });

    // 鼠标离开图表：取消所有 hover
    chartInstance.on('globalout', () => {
        if (hoveredIndex === '') return;

        const targetSeries = option.series[hoveredIndex];
        const k = targetSeries.pieStatus.k;
        const { startRatio, endRatio, value } = targetSeries.pieData;
        const isSelected = targetSeries.pieStatus.selected;

        // 取消 hover 状态
        targetSeries.parametricEquation = getParametricEquation(startRatio, endRatio, isSelected, false, k, value);
        targetSeries.pieStatus.hovered = false;
        hoveredIndex = '';

        chartInstance.setOption(option);
    });
};

// 8. 组件生命周期：挂载时初始化，卸载时销毁
onMounted(() => {
    initChart();
});

onUnmounted(() => {
    if (chartInstance) {
        chartInstance.dispose();
        chartInstance = null;
    }
});
</script>

<style scoped>
.pie3d-container {
    background-color: #0f172a;
    /* 深色背景，突出 3D 效果 */
}
</style>